﻿using FileToVideo.AddFunc;
using FileToVideo.Config;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace FileToVideo.Helpers
{
    /// <summary>
    /// 纯色帧工具
    /// </summary>
    public class PureColorFrameDetector
    {
        /// <summary>
        /// 版本控制
        /// <br />
        /// 当前数据工具版本,用于数据兼容性判断
        /// <br />
        /// 规则: 主版本.次版本.修订版本(如: 1.0.0)
        /// <br />
        /// 当主版本变化时,表示不兼容的重大变化
        /// </summary>
        [System.ComponentModel.Description("版本号")]
        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] // 防止在智能感知中显示此属性
        public static string Version { get; } = Setting.Version;

        /// <summary>
        /// 检测视频中的纯色帧并返回帧索引
        /// </summary>
        /// <param name="videoPath">视频文件路径</param>
        /// <param name="colorThreshold">颜色差异阈值（0-255）</param>
        /// <param name="pixelPercentage">纯色像素百分比阈值</param>
        /// <returns>纯色帧的索引列表</returns>
        public static List<int> FindPureColorFrames(string videoPath,
            double colorThreshold = Setting.colorTolerance,
            double pixelPercentage = 0.95)
        {
            var pureFrameIndices = new List<int>();

            using (var capture = new VideoCapture(videoPath))
            {
                if (!capture.IsOpened())
                {
                    throw new Exception("无法打开视频文件");
                }

                int frameIndex = 0;
                Mat frame = new Mat();

                while (capture.Read(frame))
                {
                    if (!frame.Empty())
                    {
                        if (IsPureColorFrame2(frame, colorThreshold, pixelPercentage))
                        {
                            pureFrameIndices.Add(frameIndex);
                            Item.logger.Log($"找到纯色帧: 索引 {frameIndex}");
                        }
                    }
                    frameIndex++;
                }
            }

            return pureFrameIndices;
        }

        /// <summary>
        /// 判断当前帧是否为纯色帧
        /// </summary>
        private static bool IsPureColorFrame(Mat frame,
            double colorThreshold = Setting.colorTolerance,
            double pixelPercentage = 0.95
        )
        {
            try
            {
                using (var labFrame = new Mat())
                {
                    Cv2.CvtColor(frame, labFrame, ColorConversionCodes.BGR2Lab);
                    Scalar meanColor = Cv2.Mean(labFrame);

                    using (var diff = new Mat())
                    {
                        Cv2.Absdiff(labFrame, new Mat(labFrame.Size(), labFrame.Type(), meanColor), diff);

                        using (var totalDiff = new Mat())
                        {
                            Mat[] channels = diff.Split();
                            Cv2.Add(channels[0], channels[1], totalDiff);
                            Cv2.Add(totalDiff, channels[2], totalDiff);

                            // 清理资源
                            foreach (Mat channel in channels)
                            {
                                channel.Dispose();
                            }

                            using (var mask = new Mat())
                            {
                                Cv2.Threshold(totalDiff, mask, colorThreshold, 255, ThresholdTypes.BinaryInv);
                                int purePixelCount = Cv2.CountNonZero(mask);
                                double purePixelRatio = (double)purePixelCount / (frame.Width * frame.Height);
                                return purePixelRatio >= pixelPercentage;
                            }
                        }
                    }
                }
            }
            finally
            {
                // 确保资源释放
                GC.Collect();
            }
        }

        /// <summary>
        /// 判断当前帧是否为纯色帧
        /// <br />
        /// 使用 ResourcesTracker 来管理资源
        /// </summary>
        private static bool IsPureColorFrame2(Mat frame,
            double colorThreshold = Setting.colorTolerance,
            double pixelPercentage = 0.95
        )
        {
            using (ResourcesTracker t = new ResourcesTracker())
            {
                Mat labFrame = t.NewMat();

                Cv2.CvtColor(frame, labFrame, ColorConversionCodes.BGR2Lab);
                Scalar meanColor = Cv2.Mean(labFrame);
                
                Mat diff = t.NewMat();

                Cv2.Absdiff(labFrame, new Mat(labFrame.Size(), labFrame.Type(), meanColor), diff);

                Mat totalDiff = t.NewMat();
                Mat[] channels = t.T(diff.Split());

                Cv2.Add(channels[0], channels[1], totalDiff);
                Cv2.Add(totalDiff, channels[2], totalDiff);

                Mat mask = t.NewMat();

                Cv2.Threshold(totalDiff, mask, colorThreshold, 255, ThresholdTypes.BinaryInv);
                int purePixelCount = Cv2.CountNonZero(mask);
                double purePixelRatio = (double)purePixelCount / (frame.Width * frame.Height);

                return purePixelRatio >= pixelPercentage;
            }
        }

        /// <summary>
        /// 检测图像是否为纯色（安全版本，自动处理彩色图像）
        /// </summary>
        /// <param name="frame">输入图像</param>
        /// <param name="threshold">颜色差异阈值，默认值为5</param>
        /// <returns>如果是纯色返回true，否则返回false</returns>
        public static bool IsSolidColorSafe(Mat frame, double threshold = Setting.colorTolerance)
        {
            // 检查输入图像是否为空
            if (frame.Empty())
                return false;

            // 如果是彩色图像（3通道），需要先转换为灰度图
            if (frame.Channels() == 3)
            {
                // 使用using语句确保灰度图资源会被正确释放
                using (Mat gray = new Mat())
                {
                    // 将BGR彩色图像转换为灰度图像
                    Cv2.CvtColor(frame, gray, ColorConversionCodes.BGR2GRAY);
                    // 调用检查函数处理灰度图
                    return CheckSolidColor(gray, threshold);
                }
            }
            else
            {
                // 如果已经是灰度图，直接进行检查
                return CheckSolidColor(frame, threshold);
            }
        }

        /// <summary>
        /// 检查灰度图像是否为纯色
        /// </summary>
        /// <param name="gray">灰度图像</param>
        /// <param name="threshold">颜色差异阈值</param>
        /// <returns>如果是纯色返回true，否则返回false</returns>
        private static bool CheckSolidColor(Mat gray, double threshold)
        {
            // 设置采样步长，避免检查每个像素，提高性能
            // 步长取图像高度的1/50，最小为1（确保至少会采样）
            int step = Math.Max(1, gray.Rows / 50);

            // 获取第一个像素的灰度值作为参考
            byte firstPixel = gray.At<byte>(0, 0);

            // 遍历图像像素（按步长采样）
            for (int i = 0; i < gray.Rows; i += step)
            {
                for (int j = 0; j < gray.Cols; j += step)
                {
                    // 获取当前像素的灰度值
                    byte currentPixel = gray.At<byte>(i, j);

                    // 如果当前像素与参考像素的差异超过阈值
                    if (Math.Abs(currentPixel - firstPixel) > threshold)
                    {
                        // 发现非纯色像素，立即返回false
                        return false;
                    }
                }
            }

            // 所有采样像素都在阈值范围内，认为是纯色
            return true;
        }

        /// <summary>
        /// 视频捕获对象
        /// </summary>
        private VideoCapture _capture;

        /// <summary>
        /// 视频地址
        /// </summary>
        private string videoPath = "";

        /// <summary>
        /// 视频地址
        /// </summary>
        public string VideoPath
        {
            get { return videoPath; }
        }

        /// <summary>
        /// 当前帧索引
        /// </summary>
        private int frameIndex = 0;

        /// <summary>
        /// 当前帧索引
        /// </summary>
        private int FrameIndex
        {
            get { return frameIndex; }
            set
            {
                if (value < 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(FrameIndex), "帧索引超出范围");
                }
                if (value > MaxFrameIndex)
                {
                    MaxFrameIndex = value;
                }
                frameIndex = value;
            }
        }

        /// <summary>
        /// 最大帧读取索引
        /// </summary>
        private int MaxFrameIndex { get; set; } = 0;

        /// <summary>
        /// 总帧数
        /// </summary>
        private int FrameCount { get; set; } = 0;

        /// <summary>
        /// 颜色差异阈值（0-255）
        /// </summary>
        private double ColorThreshold { get; set; } = Setting.colorTolerance;

        /// <summary>
        /// 纯色像素百分比阈值
        /// </summary>
        private double PixelPercentage { get; set; } = 0.95;

        /// <summary>
        /// 纯色帧颜色缓存
        /// </summary>
        private Dictionary<int, Color> pureColorCache = new Dictionary<int, Color>();

        /// <summary>
        /// 获取视频总帧数
        /// </summary>
        public int TotalFrames { get; set; }

        /// <summary>
        /// 获取视频FPS
        /// </summary>
        public double Fps { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="videoPath"></param>
        /// <param name="isRead">是否是读取模式</param>
        public PureColorFrameDetector(string videoPath, double colorThreshold, double pixelPercentage,bool isRead = true)
        {
            this._capture = new VideoCapture(videoPath);
            this.videoPath = videoPath;
            this.ColorThreshold = colorThreshold;
            this.PixelPercentage = pixelPercentage;

            // 获取总帧数
            if (isRead)
            {
                if (!_capture.IsOpened())
                {
#if DEBUG
                    MessageBox.Show(videoPath + "文件无法打开!");
#else
                    Item.logger.Log(videoPath + "文件无法打开!");
#endif
                }
                this.FrameCount = (int)_capture.Get(VideoCaptureProperties.FrameCount);
                this.Fps = _capture.Get(VideoCaptureProperties.Fps);
                this.TotalFrames = this.FrameCount;
            }

            // 获取总帧数后才能设置帧索引
            this.FrameIndex = 0;

            // 初始化最大帧索引
            this.MaxFrameIndex = 0;
            this.pureColorCache.Clear();
        }

        /// <summary>
        /// 构造函数，使用默认参数
        /// </summary>
        /// <param name="videoPath"></param>
        public PureColorFrameDetector(string videoPath,bool isRead=true) : 
            this(videoPath, Setting.colorTolerance, 0.95,isRead)
        {
        }

        /// <summary>
        /// 重置帧索引
        /// </summary>
        public void ResetIndex(int frameIndex = 0)
        {
            this.FrameIndex = frameIndex;
        }

        /// <summary>
        /// 获取下一个纯色帧的索引
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public int GetNextPureColorFrameIndex()
        {
            return GetNextPureColorFrameIndexAndColor().Item1;
        }

        /// <summary>
        /// 获取纯色帧的颜色
        /// </summary>
        /// <param name="frameIndex"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public Color GetPureColorAtFrame(int frameIndex)
        {
            using (var capture = new VideoCapture(videoPath))
            {
                if (!capture.IsOpened())
                {
                    throw new Exception("无法打开视频文件");
                }
                using (Mat frame = new Mat())
                {
                    capture.Set(VideoCaptureProperties.PosFrames, frameIndex);
                    if (capture.Read(frame))
                    {
                        if (!frame.Empty())
                        {
                            // 计算图像的平均颜色
                            Scalar meanColor = Cv2.Mean(frame);
                            return Color.FromArgb((int)meanColor.Val2, (int)meanColor.Val1, (int)meanColor.Val0);
                        }
                    }
                }
            }
            throw new Exception("无法读取指定帧");
        }

        /// <summary>
        /// 获取下一个纯色帧的索引和颜色
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public (int, Color) GetNextPureColorFrameIndexAndColor()
        {
            if (FrameIndex < MaxFrameIndex)
            {
                while (FrameIndex < MaxFrameIndex)
                {
                    if (pureColorCache.ContainsKey(FrameIndex))
                    {
                        Color color = pureColorCache[FrameIndex];
                        int foundIndex = FrameIndex;
                        FrameIndex++;
                        return (foundIndex, color);
                    }
                    FrameIndex++;
                }
            }
            else
            {
                if (!_capture.IsOpened())
                {
                    throw new Exception("无法打开视频文件");
                }
                using (Mat frame = new Mat())
                {
                    while (FrameIndex < FrameCount)
                    {
                        _capture.Set(VideoCaptureProperties.PosFrames, FrameIndex);
                        if (_capture.Read(frame))
                        {
                            if (!frame.Empty())
                            {
                                if (IsPureColorFrame2(frame, ColorThreshold, PixelPercentage))
                                {
                                    // 计算图像的平均颜色
                                    Scalar meanColor = Cv2.Mean(frame);
                                    Color color = Color.FromArgb((int)meanColor.Val2, (int)meanColor.Val1, (int)meanColor.Val0);
                                    int foundIndex = FrameIndex;
                                    FrameIndex++;
                                    pureColorCache[foundIndex] = color;
                                    return (foundIndex, color);
                                }
                            }
                        }
                        FrameIndex++;
                        frame.Dispose();
                    }
                }                
            }
            return (-1, Color.Empty); // 没有找到更多纯色帧
        }

        /// <summary>
        /// 获取下一个纯色帧的索引和颜色，不使用缓存
        /// </summary>
        /// <returns></returns>
        public (int, Color) GetNextPureColorFrameIndexAndColorNoCache()
        {
            if (!_capture.IsOpened())
            {
                throw new Exception("无法打开视频文件");
            }
            if (FrameIndex < FrameCount)
            {
                using (Mat frame = new Mat())
                {
                    while (FrameIndex < FrameCount)
                    {
                        _capture.Set(VideoCaptureProperties.PosFrames, FrameIndex);
                        _capture.Read(frame);

                        if (!frame.Empty())
                        {
                            if (IsSolidColorSafe(frame))
                            {
                                Color color = GetAverageColor(frame);
                                return (FrameIndex++, color);
                            }
                        }
                        FrameIndex++;
                    }
                }
            }
            return (-1, Color.Empty); // 没有找到更多纯色帧
        }

        /// <summary>
        /// 跳转到指定帧索引
        /// 此方法会更新最大帧索引
        /// </summary>
        /// <param name="frameIndex"></param>
        public void JumpToFrame(int frameIndex)
        {
            this.FrameIndex = frameIndex;
            this.MaxFrameIndex = frameIndex;
        }

        /// <summary>
        /// 重置检测器状态
        /// </summary>
        public void Reset()
        {
            this.FrameIndex = 0;
            this.MaxFrameIndex = 0;
            this.pureColorCache.Clear();
        }

        /// <summary>
        /// 检测特定颜色序列的起始位置
        /// </summary>
        /// <param name="colorSequence">颜色序列</param>
        /// <param name="minSequenceLength">最小序列长度阈值</param>
        /// <param name="colorTolerance">颜色容差</param>
        /// <returns>序列起始帧索引，如果未找到返回-1</returns>
        public int DetectColorSequence(
            List<Color> colorSequence, 
            int minSequenceLength = Setting.minSequenceLength, 
            double colorTolerance = Setting.colorTolerance
        )
        {
            if (colorSequence == null || colorSequence.Count == 0)
                return -1;

            int currentColorIndex = 0;
            int sequenceStartIndex = -1;
            int currentColorStartIndex = -1;
            int consecutiveCount = 0;

            for (int frameIndex = 0; frameIndex < TotalFrames; frameIndex++)
            {
                using (Mat frame = new Mat())
                {
                    _capture.Set(VideoCaptureProperties.PosFrames, frameIndex);
                    _capture.Read(frame);

                    if (frame.Empty())
                        continue;

                    Color currentColor = colorSequence[currentColorIndex];
                    bool isTargetColor = IsColorMatch(frame, currentColor, colorTolerance);

                    if (isTargetColor)
                    {
                        if (currentColorStartIndex == -1)
                        {
                            currentColorStartIndex = frameIndex;
                        }
                        consecutiveCount++;

                        // 如果当前颜色连续帧数达到最小要求，检查是否可以切换到下一个颜色
                        if (consecutiveCount >= minSequenceLength)
                        {
                            // 如果是序列的第一个颜色，记录起始位置
                            if (currentColorIndex == 0 && sequenceStartIndex == -1)
                            {
                                sequenceStartIndex = currentColorStartIndex;
                            }

                            // 尝试寻找下一个颜色的开始
                            if (currentColorIndex < colorSequence.Count - 1)
                            {
                                int nextColorStart = FindNextColorStart(frameIndex + 1,
                                    colorSequence[currentColorIndex + 1],
                                    minSequenceLength,
                                    colorTolerance);

                                if (nextColorStart != -1)
                                {
                                    currentColorIndex++;
                                    frameIndex = nextColorStart - 1; // -1 因为循环会自增
                                    currentColorStartIndex = -1;
                                    consecutiveCount = 0;

                                    // 如果已经找到所有颜色，返回序列起始位置
                                    if (currentColorIndex == colorSequence.Count - 1)
                                    {
                                        return sequenceStartIndex;
                                    }
                                }
                            }
                            else
                            {
                                // 已经找到所有颜色序列
                                return sequenceStartIndex;
                            }
                        }
                    }
                    else
                    {
                        // 当前颜色中断，重置状态
                        if (consecutiveCount > 0)
                        {
                            currentColorIndex = 0;
                            sequenceStartIndex = -1;
                            currentColorStartIndex = -1;
                            consecutiveCount = 0;
                        }
                    }
                }
            }

            return -1;
        }

        /// <summary>
        /// 从指定位置开始寻找下一个颜色的起始位置
        /// </summary>
        private int FindNextColorStart(
            int startFrame, 
            Color targetColor, 
            int minLength = Setting.minSequenceLength, 
            double tolerance = Setting.colorTolerance
        )
        {
            int consecutiveCount = 0;
            int startIndex = -1;

            for (int i = startFrame; i < TotalFrames; i++)
            {
                using (Mat frame = new Mat())
                {
                    _capture.Set(VideoCaptureProperties.PosFrames, i);
                    _capture.Read(frame);

                    if (frame.Empty())
                        continue;

                    if (IsColorMatch(frame, targetColor, tolerance))
                    {
                        if (startIndex == -1)
                            startIndex = i;

                        consecutiveCount++;

                        if (consecutiveCount >= minLength)
                            return startIndex;
                    }
                    else
                    {
                        // 颜色中断，重置计数
                        if (consecutiveCount > 0)
                            return -1;
                    }
                }
            }

            return -1;
        }

        /// <summary>
        /// 判断帧是否匹配目标颜色
        /// </summary>
        private bool IsColorMatch(Mat frame, Color targetColor, double tolerance = Setting.colorTolerance)
        {
            // 转换为Lab颜色空间以获得更好的颜色差异计算
            Mat labFrame = new Mat();
            Cv2.CvtColor(frame, labFrame, ColorConversionCodes.BGR2Lab);

            // 计算平均颜色
            Scalar meanColor = Cv2.Mean(labFrame);

            // 计算与目标颜色的差异（转换为Lab）
            Color targetLab = RgbToLab(targetColor);
            double diff = CalculateColorDifference(
                new Vec3b((byte)meanColor.Val0, (byte)meanColor.Val1, (byte)meanColor.Val2),
                new Vec3b(targetLab.R, targetLab.G, targetLab.B));

            labFrame.Dispose();

            return diff <= tolerance;
        }

        /// <summary>
        /// 计算两个Lab颜色之间的差异
        /// </summary>
        public double CalculateColorDifference(Vec3b color1, Vec3b color2)
        {
            double L_diff = color1.Item0 - color2.Item0;
            double a_diff = color1.Item1 - color2.Item1;
            double b_diff = color1.Item2 - color2.Item2;

            return Math.Sqrt(L_diff * L_diff + a_diff * a_diff + b_diff * b_diff);
        }

        /// <summary>
        /// RGB转Lab（简化版本）
        /// </summary>
        private Color RgbToLab(Color rgb)
        {
            // 简化转换，实际应用中可能需要更精确的转换
            double r = rgb.R / 255.0;
            double g = rgb.G / 255.0;
            double b = rgb.B / 255.0;

            // 简化的RGB转Lab转换
            double L = (0.2126 * r + 0.7152 * g + 0.0722 * b) * 100;
            double a = (1.4749 * (0.2210 * r - 0.3390 * g + 0.1180 * b) + 128);
            double bb = (0.6245 * (0.1940 * r + 0.3840 * g - 0.5780 * b) + 128);

            return Color.FromArgb(
                (int)Math.Max(0, Math.Min(255, L * 2.55)),
                (int)Math.Max(0, Math.Min(255, a)),
                (int)Math.Max(0, Math.Min(255, bb))
            );
        }

        /// <summary>
        /// 获取帧的平均颜色
        /// </summary>
        private Color GetAverageColor(Mat frame)
        {
            if (frame.Empty())
                return Color.Empty;

            // 计算平均颜色
            Scalar meanColor = Cv2.Mean(frame);
            return Color.FromArgb(
                (int)meanColor.Val2,  // BGR顺序：OpenCV使用BGR，Color使用RGB
                (int)meanColor.Val1,
                (int)meanColor.Val0
            );
        }

        /// <summary>
        /// 判断颜色是否匹配
        /// </summary>
        public bool IsColorMatch(Color color1, Color color2, double tolerance)
        {
            double diffR = Math.Abs(color1.R - color2.R);
            double diffG = Math.Abs(color1.G - color2.G);
            double diffB = Math.Abs(color1.B - color2.B);

            return diffR <= tolerance && diffG <= tolerance && diffB <= tolerance;
        }

        /// <summary>
        /// 根据帧索引读取视频帧
        /// <br />
        /// 使用此方法会重新打开视频文件，效率较低
        /// </summary>
        /// <param name="videoPath"></param>
        /// <param name="frameIndex"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public Mat ReadVideoFrameByIndex(string videoPath, int frameIndex)
        {
            // 创建VideoCapture对象
            using (var capture = new VideoCapture(videoPath))
            {
                // 检查视频是否成功打开
                if (!capture.IsOpened())
                {
                    throw new Exception("无法打开视频文件");
                }

                // 获取视频总帧数，用于验证索引有效性
                int totalFrames = (int)capture.Get(VideoCaptureProperties.FrameCount);
                if (frameIndex < 0 || frameIndex >= totalFrames)
                {
                    throw new ArgumentOutOfRangeException(nameof(frameIndex), "帧索引超出有效范围");
                }

                // 设置要读取的帧位置
                capture.Set(VideoCaptureProperties.PosFrames, frameIndex);

                // 读取指定帧
                Mat frame = new Mat();
                bool success = capture.Read(frame);

                if (!success || frame.Empty())
                {
                    throw new Exception("读取指定帧失败");
                }

                capture.Release();
                return frame;
            }            
        }

        /// <summary>
        /// 从指定位置开始检测颜色序列
        /// <br />
        /// 此方法会打开 Loading 界面
        /// </summary>
        /// <param name="colorSequence">颜色序列</param>
        /// <param name="startIndex">起始帧索引</param>
        /// <param name="minSequenceLength">最小序列长度</param>
        /// <param name="maxSequenceLength">最大序列长度阈值</param>"
        /// <param name="colorTolerance">颜色容差</param>
        /// <returns>序列起始帧索引，如果未找到返回-1</returns>
        public async Task<int> DetectColorSequenceFromIndex(List<Color> colorSequence, 
            int startIndex = 0,
            int minSequenceLength = Setting.minSequenceLength,
            int maxSequenceLength = Setting.maxSequenceLength,
            double colorTolerance = Setting.colorTolerance
        )
        {
            if (colorSequence == null || colorSequence.Count == 0)
                return -1;

            // 打开 Loading 界面
            using (Loading loading = new Loading(TotalFrames, "正在查询起始纯色序列..."))
            {
                loading.Show();

                // 启动后台任务
                return await Task.Run(() =>
                {
                    int currentColorIndex = 0;
                    int sequenceStartIndex = -1;
                    int consecutiveCount = 0;
                    Color lastColor = Color.Empty;
                    int consecutiveMaxCount = 0;

                    for (int frameIndex = startIndex; frameIndex < TotalFrames; frameIndex++)
                    {
                        using (Mat frame = new Mat())
                        {
                            _capture.Set(VideoCaptureProperties.PosFrames, frameIndex);
                            _capture.Read(frame);

                            // 更新 Loading 界面进度
                            loading.Dispatcher.BeginInvoke(new Action(() =>
                            {
                                loading.Update(frameIndex, "正在查询起始纯色序列" + ".".Repeat(frameIndex % 4));
                            }), System.Windows.Threading.DispatcherPriority.Background);

                            if (frame.Empty())
                                continue;

                            Color currentTargetColor = colorSequence[currentColorIndex];
                            Color frameColor = GetAverageColor(frame);

                            if (IsColorMatch(frameColor, currentTargetColor, colorTolerance))
                            {
                                consecutiveCount++;
                                consecutiveMaxCount++;
                                if (consecutiveMaxCount > maxSequenceLength)
                                {
                                    consecutiveMaxCount = consecutiveCount;
                                }
                                lastColor = frameColor;

                                if (consecutiveCount >= minSequenceLength)
                                {
                                    if (currentColorIndex == 0)
                                    {
                                        sequenceStartIndex = frameIndex - consecutiveCount + 1;
                                    }

                                    // 移动到下一个颜色
                                    currentColorIndex++;
                                    consecutiveCount = 0;

                                    // 如果已经找到所有颜色
                                    if (currentColorIndex >= colorSequence.Count)
                                    {
                                        return sequenceStartIndex;
                                    }
                                }
                            }
                            else
                            {
                                if (frameColor == lastColor && consecutiveMaxCount <= maxSequenceLength)
                                {
                                    consecutiveMaxCount++;
                                    // 继续保持当前颜色计数
                                    continue;
                                }
                                else
                                {
                                    // 颜色不匹配，重置状态
                                    currentColorIndex = 0;
                                    sequenceStartIndex = -1;
                                    consecutiveCount = 0;
                                    consecutiveMaxCount = 0;
                                }
                            }
                        }
                    }

                    return -1;
                });
            }
        }

        /// <summary>
        /// 获取指定帧
        /// </summary>
        public Mat GetFrame(int frameIndex)
        {
            _capture.Set(VideoCaptureProperties.PosFrames, frameIndex);
            Mat frame = new Mat();
            _capture.Read(frame);
            return frame;
        }

        /// <summary>
        /// 创建一个纯色帧列表
        /// <br />
        /// 最好别用这个方法创建太多帧，会占用大量内存(尤其是1080P以上分辨率)
        /// </summary>
        /// <returns></returns>
        public List<Mat> CreateColorFrame(
            List<Color> startColors,
            int frameRepetition = Setting.frameRepetition,
            int width = Setting.width,
            int height = Setting.height
        )
        {
            var ret = new List<Mat>();
            for (int i = 0; i < startColors.Count; i++)
            {
                var c = startColors[i];
                Scalar color = new Scalar(c.B,c.G,c.R);

                // 创建Mat并设置颜色
                using (Mat mat = new Mat(height, width, MatType.CV_8UC3))
                {
                    mat.SetTo(color);

                    // 重复拷贝Mat并返回
                    for (int j = 0; j < frameRepetition; j++)
                    {
                        ret.Add(mat.Clone());
                    }
                }
            }
            return ret;
        }

        /// <summary>
        /// 创建单一颜色的纯色帧
        /// </summary>
        /// <param name="color"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public Mat CreateColorFrame(
            Color color,
            int width = Setting.width,
            int height = Setting.height
        )
        {
            Scalar scalarColor = new Scalar(color.B, color.G, color.R);
            // 创建Mat并设置颜色
            Mat mat = new Mat(height, width, MatType.CV_8UC3);
            mat.SetTo(scalarColor);
            return mat;
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            _capture?.Release();
            _capture?.Dispose();
        }
    }
}
